<?php

    /**
     * 自制模板引擎
     * 模板修改，自动重新生成新的编译缓存。
     */

    class Tpl
    {
        
        public $templateDir         =   './template/';          //定义默认模板文件的路径
        public $compileDir          =   './compile';            //模板编译文件的路径
        public $tplSuffix           =   '.html';                //默认模板文件的后缀
        public $leftDelimiter       =   '{';                    //模板标签左侧分隔符
        public $rightDelimiter      =   '}';                    //模板标签右侧分隔符

        private $realTemplateDir    =   '';                     //模板目录真实路径
        private $realCompileDir     =   '';                     //编译缓存目录真实路径
        private $assignedVars        =   array();                //存储通过assign方法存储的变量
        private $templateFile       =   '';                     //模板文件
        private $compiledFile       =   '';                     //编译缓存文件

        function __construct()
        {
            if(!headers_sent()){
                header('Content-Type:text/html;charset=utf-8');
            }
            $this->setConstants();
            //检测模板文件路径和模板编译文件路径的正确性
            $this->checkDirs();
        }

        private function setConstants(){
            !defined('__DIR__') && define('__DIR__', dirname(__FILE__));
        }

        /**
         * 检测设置的模板目录及模板编译缓存目录是否正确
         */
        private function checkDirs(){
            //设置真实的模板目录路径及编译缓存目录路径，可自动区分是否为绝对路径
            $this->realTemplateDir = file_exists_case($this->templateDir) ? $this->templateDir : realpath(__DIR__.'/'.$this->templateDir);
            $this->realCompileDir  = file_exists_case($this->compileDir)  ? $this->compileDir  : realpath(__DIR__.'/'.$this->compileDir);
            if( !file_exists_case($this->realTemplateDir) ){
                $this->error('模板目录路径有误！');
            }
            if( !file_exists_case($this->realCompileDir) ){
                $this->error('模板编译目录路径有误！');
            }
        }

        public function assign($tplVar, $var=null)
        {
            if( is_null($var) ){

            }else{
                if( !is_null($tplVar) ){
                    $this->assignedVars[$tplVar] = $var;
                }else{
                    if(is_array($tplVar)){

                    }
                }                
            }
        }

        public function display($template)
        {
            //获取模板文件和编译缓存文件
            $this->templateFile = $this->realTemplateDir.'/'.$template.$this->tplSuffix;
            if( !file_exists_case($this->templateFile) ){
                $this->error('模板文件'.$template.'不存在！');
            }
            $this->compiledFile = $this->realCompileDir.'/'.md5( $this->templateFile.filemtime($this->templateFile) ).'.php';
            
            /*
            方案1：如果缓存文件存在，且模板未改动过，则使用编译缓存的内容，原理是判断文件+文件修改时间的md5值的.php
            文件是否存在。这个文件存在，就说明模板编译缓存文件存在，也就说明这个文件为更改。修改时间变化md5值必然
            变化，模板缓存文件名必然变化。
            方案2：其实还有另外一种方案，根据流程，缓存文件生成时间肯定比模板大，那么模板的修改时间比缓存生成时间大，
            就说明模板文件被更改了
            本程序使用第一种方案
            */
            if( file_exists_case($this->compiledFile) ){
                include $this->compiledFile;
                error_log("sss\r\n",3,'count.txt');
            }else{
                //获取模板文件内容
                $tplContent = file_get_contents($this->templateFile);
                //正则替换模板标签
                $pattern = array(
                        '/\{\s*\$([a-zA-Z][a-zA-Z0-9]*)\s*\}/',
                    );
                $replacement = array(
                        '<?php echo $this->assignedVars["${1}"] ?>'
                    );
                $repalcedStr = preg_replace($pattern, $replacement, $tplContent);
                //获取编译缓存文件
                file_put_contents($this->compiledFile, $repalcedStr);
                include $this->compiledFile;
                error_log("sss\r\n",3,'count2.txt');
            }

        }

        //报错函数
        final public function error($msg, $level=1, $ifLog=0){
            die($msg);
        }
    }

    function file_exists_case($filename) {
        if(is_file($filename) || is_dir($filename)) {
            if( is_win() ) {
                if(basename(realpath($filename)) != basename($filename)){
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    function is_win(){
        return strstr(PHP_OS, 'WIN') ? true : false ;
    }
?>